<template>
  <uploader
    ref="uploader"
    :options="options"
    :file-status-text="statusText"
    class="uploader-example"
    @file-added="fileAdded"
    @file-complete="fileComplete"
    @complete="complete"
    @file-success="fileSuccess"
  >
    <uploader-unsupport></uploader-unsupport>
    <uploader-drop>
      <p v-if="fileName">当前文件名： {{ fileName }}</p>
      <p v-else>选择文件或拖拽文件</p>
      <uploader-btn>选择文件</uploader-btn>
    </uploader-drop>
    <uploader-list></uploader-list>
  </uploader>
</template>
  
<script>
import { getToken } from '@/utils/auth';
import defaultSettings from '@/settings';
import { getParamsWithMerge } from '../../utils/common-methods';
import { Base64 } from 'js-base64';
import jp from 'jsonpath';

export default {
  name: 'SimpleUploader',
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    ajaxSetting: {
      type: Object,
      default: () => {}
    },
    singleFile: {
      type: Boolean,
      default: false
    },
    chunkSize: {
      type: Number,
      default: 1048576
    },
    simultaneousUploads: {
      type: Number,
      default: 3
    },
    fileParameterName: {
      type: String,
      default: 'file'
    },
    nameParameterName: {
      type: String,
      default: undefined
    },
    withCredentials: {
      type: Boolean,
      default: false
    },
    maxChunkRetries: {
      type: Number,
      default: 0
    },
    chunkRetryInterval: {
      type: Number,
      default: null
    },
    fileAddedHook: {
      type: Function,
      default: () => {}
    },
    completeHook: {
      type: Function,
      default: () => {}
    }
  },
  data() {
    return {
      fileName: '',
      options: {},
      attrs: {
        accept: 'image/*'
      },
      statusText: {
        success: 'success',
        error: 'error',
        uploading: 'uploading',
        paused: 'paused',
        waiting: 'waiting'
      }
    };
  },
  computed: {
    baseUrl() {
      return import.meta.env.VITE_APP_BASE_API;
    }
  },
  watch: {
    modelValue: {
      handler(val) {
        if (val) {
          this.fileName = val;
        }
      },
      immediate: true
    }
  },
  created() {
    this.initOptions();
  },
  methods: {
    getAjaxSettingConfig() {
      try {
        const { type, url, method, contentType, headers, params, hookBefore } = this.ajaxSetting;
        const anvilCodeStore = this.useAnvilCodeStore();
        const { instance } = anvilCodeStore.getPageForm(this.$attrs.pageId);
        let Header = {},
          Param = {},
          HeadersMap = {};
        if (headers) {
          headers.map((item) => {
            HeadersMap[item.key] = item.value;
          });
        }
        Header[defaultSettings.tokenName] = 'Bearer ' + getToken();

        Param = getParamsWithMerge(this, params);

        if (hookBefore) {
          console.log('调用前置钩子', hookBefore);
          Param = instance[hookBefore](Param);
        }

        if (type == 'ajax') {
          Param.apiId = url;

          return {
            url: this.baseUrl + '/conn/api/upload',
            headers: Header,
            params: Param,
            HeadersMap
          };
        } else {
          return {
            url,
            method,
            contentType,
            headers: { ...Header, ...HeadersMap },
            params: Param
          };
        }
      } catch (e) {
        console.log('getAjaxSettingConfig Error!', e);
        return {};
      }
    },
    initOptions() {
      const config = this.getAjaxSettingConfig();
      const { type, url } = this.ajaxSetting;
      this.options = {
        target: config.url,
        headers: config.headers,
        query: (file) => {
          const fileInfo = {
            ...config.params,
            [this.nameParameterName]: this.nameParameterName ? file.name : undefined
          };
          if (type === 'ajax') {
            return { apiId: url, reqBodyBase64: Base64.encode(JSON.stringify(fileInfo)), reqHeaderBase64: Base64.encode(JSON.stringify(config.HeadersMap)) };
          }
          return fileInfo;
        },
        testChunks: false,
        testMethod: 'post',
        uploadMethod: 'post',
        singleFile: this.singleFile,
        chunkSize: this.chunkSize,
        simultaneousUploads: this.simultaneousUploads,
        fileParameterName: this.fileParameterName,
        withCredentials: this.withCredentials,
        maxChunkRetries: this.maxChunkRetries,
        chunkRetryInterval: this.chunkRetryInterval
      };
    },
    complete() {
      console.log('complete', arguments);
      if (this.completeHook && typeof this.completeHook === 'function') {
        this.completeHook();
      }
    },
    // 文件添加时钩子，返回false则文件会被忽略
    fileAdded(file, event) {
      console.log('file added', file);
      this.fileName = '';
      if (this.fileAddedHook && typeof this.fileAddedHook === 'function') {
        this.fileAddedHook(file, event);
      }
    },
    // 文件上传完毕
    fileComplete() {
      console.log('file complete', arguments);
    },
    // 文件上传成功
    fileSuccess(rootFile, file, message, chunk) {
      console.log('file success', arguments);
      const anvilCodeStore = this.useAnvilCodeStore();
      const { instance } = anvilCodeStore.getPageForm(this.$attrs.pageId);
      const { hookAfter, callbackJsonPath, formFill } = this.ajaxSetting;
      if (message) {
        const result = JSON.parse(message);
        let data = result;
        if (hookAfter) {
          data = instance[hookAfter](data);
        }
        data = jp.query(data, callbackJsonPath ? callbackJsonPath : '$');
        console.log('回填前数据', data);
        // 有表单回填先执行表单回填
        if (formFill) {
          if (data && data.length) {
            instance.setFormData(data[0]);
          }
        }
      }
    }
  }
};
</script>
  
<style scoped lang="scss">
.uploader-example {
  width: 880px;
  padding: 15px;
  margin: 40px auto 0;
  font-size: 12px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.4);
}
.uploader-example .uploader-btn {
  margin-right: 4px;
}
.uploader-example .uploader-list {
  max-height: 440px;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
}
</style>